<?php
/*

	self a stemming class for spanish / Un lexemador para español
    Copyright (C) 2007  Paolo Ragone

    This library is free software; you can redistribute it and/or
    modify it under the terms of the GNU Lesser General Public
    License as published by the Free Software Foundation; either
    version 2.1 of the License, or (at your option) any later version.

    This library is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
    Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public
    License along with this library; if not, write to the Free Software
    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
	or go to: http://www.gnu.org/licenses/lgpl.txt

	You may contact me at pragone@gmail.com

*/

class CPtPorterStemmer {

	function is_vowel($c) {
		return ($c == 'a' || $c == 'e' || $c == 'i' || $c == 'o' || $c == 'u' || $c == 'á' || $c == 'é' ||
			$c == 'í' || $c == 'ó' || $c == 'ú');
	}

	function getNextVowelPos($word, $start = 0) {
		$len = strlen($word);
		for ($i = $start; $i < $len; $i++)
			if (self::is_vowel($word[$i])) return $i;
		return $len;
	}

	function getNextConsonantPos($word, $start = 0) {
		$len = strlen($word);
		for ($i = $start; $i < $len; $i++)
			if (!self::is_vowel($word[$i])) return $i;
		return $len;		
	}

	function endsin($word, $suffix) {
		if (strlen($word) < strlen($suffix)) return false;
		return (substr($word, -strlen($suffix)) == $suffix);
	}

	function endsinArr($word, $suffixes) {
		foreach ($suffixes as $suff) {
			if (self::endsin($word, $suff)) return $suff;
		}
		return '';
	}

	function removeAccent($word) {
		return str_replace(array('á','é','í','ó','ú'), array('a','e','i','o','u'), $word);
	}

	function Stem($word) {
		$len = strlen($word);
		if ($len <=2) return $word;

		$word = strtolower($word);

		$r1 = $r2 = $rv = $len;
		//R1 is the region after the first non-vowel following a vowel, or is the null region at the end of the word if there is no such non-vowel.
		for ($i = 0; $i < ($len-1) && $r1 == $len; $i++) {
			if (self::is_vowel($word[$i]) && !self::is_vowel($word[$i+1])) { 
					$r1 = $i+2;
			}
		}

		//R2 is the region after the first non-vowel following a vowel in R1, or is the null region at the end of the word if there is no such non-vowel. 
		for ($i = $r1; $i < ($len -1) && $r2 == $len; $i++) {
			if (self::is_vowel($word[$i]) && !self::is_vowel($word[$i+1])) { 
				$r2 = $i+2; 
			}
		}

		if ($len > 3) {
			if(!self::is_vowel($word[1])) {
				// If the second letter is a consonant, RV is the region after the next following vowel
				$rv = self::getNextVowelPos($word, 2) +1;
			} elseif (self::is_vowel($word[0]) && self::is_vowel($word[1])) { 
				// or if the first two letters are vowels, RV is the region after the next consonant
				$rv = self::getNextConsonantPos($word, 2) + 1;
			} else {
				//otherwise (consonant-vowel case) RV is the region after the third letter. But RV is the end of the word if these positions cannot be found.
				$rv = 3;
			}
		}

		$r1_txt = substr($word,$r1);
		$r2_txt = substr($word,$r2);
		$rv_txt = substr($word,$rv);

		$word_orig = $word;

		// Step 0: Attached pronoun
		$pronoun_suf = array('me', 'se', 'sela', 'selo', 'selas', 'selos', 'la', 'le', 'lo', 'las', 'les', 'los', 'nos');	
		$pronoun_suf_pre1 = array('éndo', 'ándo', 'ár', 'ér', 'ír');	
		$pronoun_suf_pre2 = array('ando', 'iendo', 'ar', 'er', 'ir');
		$suf = self::endsinArr($word, $pronoun_suf);
		if ($suf != '') {
			$pre_suff = self::endsinArr(substr($rv_txt,0,-strlen($suf)),$pronoun_suf_pre1);
			if ($pre_suff != '') {
				$word = self::removeAccent(substr($word,0,-strlen($suf)));
			} else {
				$pre_suff = self::endsinArr(substr($rv_txt,0,-strlen($suf)),$pronoun_suf_pre2);
				if ($pre_suff != '' ||
					(self::endsin($word, 'yendo' ) && 
					(substr($word, -strlen($suf)-6,1) == 'u'))) {
					$word = substr($word,0,-strlen($suf));
				}
			}
		}
		
		if ($word != $word_orig) {
			$r1_txt = substr($word,$r1);
			$r2_txt = substr($word,$r2);
			$rv_txt = substr($word,$rv);
		}
		$word_after0 = $word;
		+"u";
		
		
	/*	private final String suffix1[] = {"amentos", "imentos", "amento", "imento", "adoras", "adores", "aço~es", "ismos", "istas",
	 *  "adora", "aça~o", "antes", "ância", "ezas", "icos", "icas", "ismo", "ável", "ível", "ista", "osos", "osas", "ador", 
	 *  "ante", "eza", "ico", "ica", "oso", "osa"};
		private final String suffix2[] ={"logías", "logía"};
		private final String suffix3[] ={"uciones", "ución"};
		private final String suffix4[] ={"ências", "ência"}; //ente
		private final String suffix5[] ={"amente"};
		private final String suffix6[] ={"mente"};
		private final String suffix7[] ={"idades", "idade"};
		private final String suffix8[] ={"ivas", "ivos", "iva", "ivo"};
		private final String suffix9[] ={"iras", "ira"};
		private final String suffixv[] = {"aríamos", "eríamos", "iríamos", "ássemos", "êssemos", "íssemos", "aríeis", "eríeis", "iríeis", "ásseis", "ésseis", "ísseis", "áramos", "éramos", "íramos", "ávamos", "aremos", "eremos", "iremos", "ariam", "eriam", "iriam", "assem", "essem", "issem", "ara~o", "era~o", "ira~o", "arias", "erias", "irias", "ardes", "erdes", "irdes", "asses", "esses", "isses", "astes", "estes", "istes", "áreis", "areis", "éreis", "ereis", "íreis", "ireis", "áveis", "íamos", 
		"armos", "ermos", "irmos", "aria", "eria", "iria", "asse", "esse", "isse", "aste", "este", "iste", "arei", "erei",
		 "irei", "aram", "eram", "iram", "avam", "arem", "erem", "irem", "ando", "endo", "indo", "adas", "idas", "arás", 
		 "aras", "erás", "eras", "irás", "avas", "ares", "eres", "ires", "íeis", "ados", "idos", "ámos", "amos", "emos", 
		 "imos", "iras", "ada", "ida", "ará", "ara", "erá", "era", "irá", "ava", "iam", "ado", "ido", "ias", "ais", "eis", 
		 "ira", "ia", "ei", "am", "em", "ar", "er", "ir", "as", "es", "is", "eu", "iu", "ou"};
		private final String suffixr[] = {"os", "a", "i", "o", "á", "í", "ó"};
		private final String suffixf[] = {"e", "é", "ê"};
		*/
		if (($suf = self::endsinArr($r2_txt, array('ança', 'ancia','anças', 'ico', 'ica', 'icos', 'icas', 'ismo', 'ismos', 'avel',
				 'aveis', 'ivel', 'iveis', 'ista', 'istas', 'oso', 'osa', 'osos', 'osas', 'eza','ezas','mento', 'amentos', 'amento',
				'imento', 'imentos'))) != '') {
			$word = substr($word,0, -strlen($suf));	
		} elseif (($suf = self::endsinArr($r2_txt, array('icadora', 'icador', 'icação', 'icadoras', 'icadores', 'icações', 'icante', 
				'icantes', 'icancia', 'icancias', 'adora', 'ador', 'ação', 'adoras', 'adores', 'ações', 'ante', 'antes'))) != '') {
			$word = substr($word,0, -strlen($suf));	
		} elseif (($suf = self::endsinArr($r2_txt, array('logía', 'logías'))) != '') {
			$word = substr($word,0, -strlen($suf)) . 'log';
		} elseif (($suf = self::endsinArr($r2_txt, array('ución', 'uciones'))) != '') {
			$word = substr($word,0, -strlen($suf)) . 'u';
		} elseif (($suf = self::endsinArr($r2_txt, array('encia', 'encias'))) != '') {
			$word = substr($word,0, -strlen($suf)) . 'ente';
		} elseif (($suf = self::endsinArr($r2_txt, array('ativamente', 'ivamente', 'osamente', 'icamente', 'adamente'))) != '') {
			$word = substr($word,0, -strlen($suf));
		} elseif (($suf = self::endsinArr($r1_txt, array('amente'))) != '') {
			$word = substr($word,0, -strlen($suf));
		} elseif (($suf = self::endsinArr($r2_txt, array('antemente', 'ablemente', 'iblemente', 'mente'))) != '') {
			$word = substr($word,0, -strlen($suf));
		} elseif (($suf = self::endsinArr($r2_txt, array('abilidade', 'abilidades', 'icidade', 'icidades', 'ividade', 'ividades', 'idade', 'idades'))) != '') {
			$word = substr($word,0, -strlen($suf));
		} elseif (($suf = self::endsinArr($r2_txt, array('ativa', 'ativo', 'ativas', 'ativos', 'iva', 'ivo', 'ivas', 'ivos'))) != '') {
			$word = substr($word,0, -strlen($suf));
		}

		if ($word != $word_after0) {
			$r1_txt = substr($word,$r1);
			$r2_txt = substr($word,$r2);
			$rv_txt = substr($word,$rv);
		}
		$word_after1 = $word;
		
		if ($word_after0 == $word_after1) {
			// Do step 2a if no ending was removed by step 1. 
			if (($suf = self::endsinArr($rv_txt, array('ia', 'ie', 'ião', 'yen', 'eron', 'yendo', 'yo', 
					'yó', 'yas', 'yes', 'yais', 'yamos'))) != '' && (substr($word,-strlen($suf)-1,1) == 'u')) {
				$word = substr($word,0, -strlen($suf));
			}
			
			if ($word != $word_after1) {
				$r1_txt = substr($word,$r1);
				$r2_txt = substr($word,$r2);
				$rv_txt = substr($word,$rv);
			}
			$word_after2a = $word;
			
			// Do Step 2b if step 2a was done, but failed to remove a suffix. 
			if ($word_after2a == $word_after1) {
				if (($suf = self::endsinArr($rv_txt, array('en', 'es', 'éis', 'emos'))) != '') {
					$word = substr($word,0, -strlen($suf));
					if (self::endsin($word, 'gu')) {
						$word = substr($word,0,-1);
					}
				} elseif (($suf = self::endsinArr($rv_txt, array("aríamos", "eríamos", "iríamos", "ássemos", "êssemos", "íssemos", "aríeis", "eríeis", "iríeis", "ásseis", "ésseis", "ísseis", "áramos", "éramos", "íramos", "ávamos", "aremos", "eremos", "iremos", "ariam", "eriam", "iriam", "assem", "essem", "issem", "ara~o", "era~o", "ira~o", "arias", "erias", "irias", "ardes", "erdes", "irdes", "asses", "esses", "isses", "astes", "estes", "istes", "áreis", "areis", "éreis", "ereis", "íreis", "ireis", "áveis", "íamos", 
		"armos", "ermos", "irmos", "aria", "eria", "iria", "asse", "esse", "isse", "aste", "este", "iste", "arei", "erei",
		 "irei", "aram", "eram", "iram", "avam", "arem", "erem", "irem", "ando", "endo", "indo", "adas", "idas", "arás", 
		 "aras", "erás", "eras", "irás", "avas", "ares", "eres", "ires", "íeis", "ados", "idos", "ámos", "amos", "emos", 
		 "imos", "iras", "ada", "ida", "ará", "ara", "erá", "era", "irá", "ava", "iam", "ado", "ido", "ias", "ais", "eis", 
		 "ira", "ia", "ei", "am", "em", "ar", "er", "ir", "as", "es", "is", "eu", "iu", "ou"))) != '') {
					$word = substr($word,0, -strlen($suf));
				}
			}
		}

		// Always do step 3. 
		$r1_txt = substr($word,$r1);
		$r2_txt = substr($word,$r2);
		$rv_txt = substr($word,$rv);

		if (($suf = self::endsinArr($rv_txt, array('os', 'a', 'i','o', 'á', 'í', 'ó'))) != '') {
			$word = substr($word,0, -strlen($suf));
		} elseif (($suf = self::endsinArr($rv_txt ,array('e','é','é'))) != '') {
			$word = substr($word,0,-1);
			$rv_txt = substr($word,$rv);
			if (self::endsin($rv_txt,'u') && self::endsin($word,'gu')) {
				$word = substr($word,0,-1);
			}
		}
		
		return self::removeAccent($word);
	}
}
?>